"""
项目配置管理模块
负责管理项目生成的各种配置选项
"""

from typing import Dict, Any, Optional, List
from pathlib import Path
import re
import yaml
import toml
from dataclasses import dataclass, field
from loguru import logger


@dataclass
class ProjectConfig:
    """项目配置类"""
    
    # 基本信息
    project_name: str = ""
    project_type: str = "fastapi"  # fastapi, cli, web, library
    description: str = ""
    author: str = "Clark"
    email: str = "changhongyuan@126.com"
    version: str = "0.1.0"
    license: str = "MIT"
    
    # 目录配置
    target_dir: str = "."
    source_dir: str = "app"
    
    # 功能选项
    use_uv: bool = True
    init_git: bool = True
    use_docker: bool = True
    use_pre_commit: bool = False
    
    # 依赖配置
    python_version: str = ">=3.13"
    dependencies: List[str] = field(default_factory=lambda: [
        "fastapi",
        "fastmcp", 
        "uvicorn",
        "loguru",
    ])
    dev_dependencies: List[str] = field(default_factory=lambda: [
        "pytest",
        "black",
        "ruff",
    ])
    
    # 模板配置
    template_overrides: Dict[str, Any] = field(default_factory=dict)
    
    # 额外配置
    extra_config: Dict[str, Any] = field(default_factory=dict)
    
    def __post_init__(self):
        """初始化后处理"""
        if not self.description:
            self.description = f"A {self.project_type} project generated by SDP-PY"
    
    def update(self, config_dict: Dict[str, Any]) -> None:
        """
        更新配置
        
        Args:
            config_dict: 配置字典
        """
        for key, value in config_dict.items():
            if hasattr(self, key):
                setattr(self, key, value)
            else:
                self.extra_config[key] = value
        
        logger.debug(f"配置已更新: {config_dict}")
    
    def get(self, key: str, default: Any = None) -> Any:
        """
        获取配置值
        
        Args:
            key: 配置键
            default: 默认值
            
        Returns:
            配置值
        """
        if hasattr(self, key):
            return getattr(self, key)
        return self.extra_config.get(key, default)
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        result = {}
        for field_name in self.__dataclass_fields__:
            result[field_name] = getattr(self, field_name)
        result.update(self.extra_config)
        return result
    
    def save_to_file(self, file_path: str) -> None:
        """
        保存配置到文件
        
        Args:
            file_path: 文件路径
        """
        config_dict = self.to_dict()
        file_path_obj = Path(file_path)
        
        if file_path_obj.suffix == '.yaml' or file_path_obj.suffix == '.yml':
            with open(file_path_obj, 'w', encoding='utf-8') as f:
                yaml.dump(config_dict, f, default_flow_style=False, allow_unicode=True)
        elif file_path_obj.suffix == '.toml':
            with open(file_path_obj, 'w', encoding='utf-8') as f:
                toml.dump(config_dict, f)
        else:
            raise ValueError(f"不支持的文件格式: {file_path_obj.suffix}")
        
        logger.info(f"配置已保存到: {file_path_obj}")
    
    @classmethod
    def load_from_file(cls, file_path: str) -> 'ProjectConfig':
        """
        从文件加载配置
        
        Args:
            file_path: 文件路径
            
        Returns:
            项目配置对象
        """
        file_path_obj = Path(file_path)
        
        if not file_path_obj.exists():
            raise FileNotFoundError(f"配置文件不存在: {file_path_obj}")
        
        if file_path_obj.suffix == '.yaml' or file_path_obj.suffix == '.yml':
            with open(file_path_obj, 'r', encoding='utf-8') as f:
                config_dict = yaml.safe_load(f)
        elif file_path_obj.suffix == '.toml':
            with open(file_path_obj, 'r', encoding='utf-8') as f:
                config_dict = toml.load(f)
        else:
            raise ValueError(f"不支持的文件格式: {file_path_obj.suffix}")
        
        config = cls()
        config.update(config_dict)
        
        logger.info(f"配置已从文件加载: {file_path_obj}")
        return config
    
    def validate(self) -> List[str]:
        """
        验证配置
        
        Returns:
            错误信息列表
        """
        errors = []
        
        # 验证项目名称
        if not self.project_name:
            errors.append("项目名称不能为空")
        elif not self.project_name.replace('-', '').replace('_', '').isalnum():
            errors.append("项目名称只能包含字母、数字、连字符和下划线")
        
        # 验证项目类型
        valid_types = ["fastapi", "fastmcp"]
        if self.project_type not in valid_types:
            errors.append(f"项目类型必须是以下之一: {', '.join(valid_types)}")
        
        # 验证版本号
        version_pattern = r'^\d+\.\d+\.\d+.*$'
        if not re.match(version_pattern, self.version):
            errors.append("版本号格式不正确，应为 x.y.z 格式")
        
        # 验证Python版本
        python_version_pattern = r'^>=\d+\.\d+$'
        if not re.match(python_version_pattern, self.python_version):
            errors.append("Python版本格式不正确，应为 >=x.y 格式")
        
        # 验证邮箱格式
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if self.email and not re.match(email_pattern, self.email):
            errors.append("邮箱格式不正确")
        
        if errors:
            logger.error(f"配置验证失败: {errors}")
        
        return errors
    
    def get_template_context(self) -> Dict[str, Any]:
        """
        获取模板渲染上下文
        
        Returns:
            模板上下文字典
        """
        context = self.to_dict()
        
        # 添加一些便利的模板变量
        context.update({
            'project_name_snake': self.project_name.replace('-', '_'),
            'project_name_kebab': self.project_name.replace('_', '-'),
            'project_name_camel': ''.join(word.capitalize() for word in self.project_name.replace('-', '_').split('_')),
            'project_name_title': self.project_name.replace('-', ' ').replace('_', ' ').title(),
            'has_fastapi': 'fastapi' in self.dependencies,
            'has_fastmcp': 'fastmcp' in self.dependencies,
            'has_click': 'click' in self.dependencies,
            'has_loguru': 'loguru' in self.dependencies,
        })
        
        return context


class ConfigManager:
    """配置管理器"""
    
    @staticmethod
    def create_default_config(project_name: str, project_type: str = "fastapi") -> ProjectConfig:
        """
        创建默认配置
        
        Args:
            project_name: 项目名称
            project_type: 项目类型
            
        Returns:
            项目配置对象
        """
        config = ProjectConfig()
        config.project_name = project_name
        config.project_type = project_type
        config.description = f"A {project_type} project generated by SDP-PY"
        
        # 根据项目类型调整依赖
        if project_type == "fastmcp":
            config.dependencies = [
                "fastmcp",
                "loguru", 
                "pyyaml",
                "rich",
                "pydantic",
                "click",
            ]
        elif project_type == "fastapi":
            config.dependencies = [
                "fastapi",
                "uvicorn",
                "loguru",
                "pydantic-settings",
            ]
        
        return config
    
    @staticmethod
    def get_project_types() -> Dict[str, str]:
        """
        获取支持的项目类型
        
        Returns:
            项目类型字典 {类型: 描述}
        """
        return {
            "fastapi": "FastAPI Web API项目",
            "fastmcp": "FastMCP服务器项目",
        }
    
    @staticmethod 
    def validate_project_name(name: str) -> bool:
        """
        验证项目名称
        
        Args:
            name: 项目名称
            
        Returns:
            是否有效
        """
        if not name:
            return False
        
        # 检查长度
        if len(name) < 2 or len(name) > 50:
            return False
        
        # 检查字符
        if not re.match(r'^[a-zA-Z0-9][a-zA-Z0-9_-]*[a-zA-Z0-9]$', name):
            return False
        
        return True